/*
 * ErrorCode.cpp
 *
 *  Created on: Aug 2, 2016
 *      Author: Lucifer
 */

#include "SocketError.h"

#include "./Common.h"
#include <boost/thread.hpp>

namespace BFX {

// The last error code is maintained on a per-thread basis. Threads will not overwrite each other's
// last error code.
static boost::thread_specific_ptr<void> __lastErrorCode;

int SocketError::get() {
	return (int) (size_t) __lastErrorCode.get();
}
void SocketError::set(int ec) {
	__lastErrorCode.reset((void*) (size_t) ec);
}
void SocketError::clear() {
	set(EC_Success);
}

void SocketError::update(bool hasError) {
	if (hasError)
		updateSysError();
	else
		clear();
}
void SocketError::updateSysError() {
	switch (errno) {
	case 0:	// No error
		set(EC_Success);
		break;
	case EACCES:	// Permission denied
		set(EC_AccessDenied);
		break;
	case EAFNOSUPPORT:	// Address family not supported by protocol family
		set(EC_AddressFamilyNotSupported);
		break;
	case EPROTONOSUPPORT: // Unknown protocol
		set(EC_ProtocolFamilyNotSupported);
		break;
	case EBADF:		// Invalid file descriptor
		set(EC_BadFileDescriptor);
		break;
	case EINTR:		// Interrupted
		set(EC_Interrupted);
		break;
	case EINVAL:	// Invalid argument
		set(EC_InvalidArgument);
		break;
	case ENFILE:	// Too many open files in system
	case EMFILE:	// File descriptor value too large
		set(EC_TooManyOpenFiles);
		break;
	case ENOBUFS:	// No buffer space available
	case ENOMEM:	// Insufficient memory is available
		set(EC_NoBufferSpaceAvailable);
		break;
	default:	// Unrecognized error code.
		set(EC_IllegalStateError);
		break;
	}
#if PLATFORM == PLATFORM_WINDOWS
	// XXX transfer error code from ::WSAGetLastError(), if necessary.
#endif
}

} /* namespace BFX */
